<!--
  * 基础弹窗组件
  * this.$refs['xx'].visiableDialog() 显示弹窗
  * this.$refs['xx'].invisiableDialog() 关闭弹窗
  * title：弹窗标题
  * width：弹窗宽度
  * cancelBtnText 取消按钮文字 默认"关闭"
  * confirmBtnText 确认按钮文字 默认"确定"
  * emit('close')、emit('confirm')、emit('opened')
  * showCancelBtn 是否显示取消按钮
  * showConfirmBtn 是否显示确认按钮
  * showFooter 是否显示底部按钮区域
  * closeOnClickModal: 点击遮罩层是否关闭弹窗
  * showClose: 是否显示右上角关闭图标
  * appendToBody: 是否插入至 body 元素上
  * cancelBtnType: 取消按钮类型
  * confirmBtnType: 确认按钮类型
  * fullscreen: 是否全屏显示
  * destroyOnClose: 关闭时销毁 Dialog 中的元素
  * 插槽支持：
  *   - content: 弹窗内容
  *   - defaultBtnBefore: 默认按钮前的插槽
  *   - defaultBtnInner: 默认按钮中间的插槽
  *   - defaultBtnAfter: 默认按钮后的插槽
  *   - subSlot: 弹窗底部额外插槽
 -->
<template>
  <div>
    <el-dialog
      v-model="dialogVisible"
      :title="title"
      :width="width"
      :before-close="handleClose"
      :close-on-click-modal="closeOnClickModal"
      :show-close="showClose"
      :fullscreen="fullscreen"
      :append-to-body="appendToBody"
      :destroy-on-close="destroyOnClose"
      center
      @opened="handleDialogOpened"
    >
      <slot name="content"></slot>
      <template #footer v-if="showFooter">
        <span class="dialog-footer">
          <slot name="defaultBtnBefore"></slot>
          <el-button
            v-if="showCancelBtn"
            size="small"
            :type="cancelBtnType"
            @click="handleClose"
            :loading="cancelBtnLoading"
          >
            {{ cancelBtnText }}
          </el-button>
          <slot name="defaultBtnInner"></slot>
          <el-button
            v-if="showConfirmBtn"
            size="small"
            :type="confirmBtnType"
            @click="handleConfirm"
            :loading="btnLoading"
          >
            {{ confirmBtnText }}
          </el-button>
          <slot name="defaultBtnAfter"></slot>
        </span>
      </template>
      <slot name="subSlot"></slot>
    </el-dialog>
  </div>
</template>
<script lang='ts' setup>
import { ref, watch } from 'vue'
import 'element-plus/theme-chalk/el-button.css'

interface IDialogProps {
  title?: string,
  width?: string,
  confirmBtnText?: string,
  cancelBtnText?: string,
  showConfirmBtn?: boolean
  showCancelBtn?: boolean
  showFooter?: boolean
  closeOnClickModal?: boolean
  showClose?: boolean
  appendToBody?: boolean
  cancelBtnType?: string
  confirmBtnType?: string
  fullscreen?: boolean
  destroyOnClose?: boolean
}

const dialogVisible = ref<boolean>(false)
const props = withDefaults(defineProps<IDialogProps>(), {
  title: 'Tips',
  width: '45%',
  showFooter: true,
  showConfirmBtn: true,
  showCancelBtn: true,
  confirmBtnText: '确定',
  cancelBtnText: '关闭',
  closeOnClickModal: false,
  showClose: false,
  appendToBody: false,
  cancelBtnType: 'info',
  confirmBtnType: 'primary',
  fullscreen: false,
  destroyOnClose: false
})

/* ------------------------------ variable ------------------------------ */
const btnLoading = ref<boolean>(false)
const cancelBtnLoading = ref<boolean>(false)

/* ------------------------------ watchers ------------------------------ */
watch(() => props.showConfirmBtn, (newVal) => {
  // 可以在这里添加额外的逻辑
})

watch(() => props.showCancelBtn, (newVal) => {
  // 可以在这里添加额外的逻辑
})

/* ------------------------------ function ------------------------------ */
const emit = defineEmits(['close', 'confirm', 'opened'])

const handleClose = () => {
  dialogVisible.value = false
  emit('close')
}

const visiableDialog = () => {
  dialogVisible.value = true
}

const invisiableDialog = () => {
  btnLoading.value = false
  dialogVisible.value = false
}

const hideBtnLoading = () => {
  btnLoading.value = false
}

const clearLoading = () => {
  btnLoading.value = false
}

const showCancelLoading = () => {
  cancelBtnLoading.value = true
}

const clearCancelLoading = () => {
  cancelBtnLoading.value = false
}

const handleConfirm = () => {
  btnLoading.value = true
  emit('confirm')
}

const handleDialogOpened = () => {
  emit('opened')
}

defineExpose({
  visiableDialog,
  invisiableDialog,
  hideBtnLoading,
  clearLoading,
  showCancelLoading,
  clearCancelLoading
})
</script>
<style scoped lang='less'>
:deep(.el-dialog__title) {
  font-size: 16px;
}

:deep(.el-dialog__header) {
  display: flex;
  justify-content: space-between;
  border-bottom: 1px solid lightgray;
}

:deep(.el-dialog__footer) {
  display: flex;
  justify-content: right;
  border-top: 1px solid lightgray;
}
</style>
